#pragma once

#include <maya/MPxContext.h>
#include <maya/MPoint.h>
#include <maya/MDagPath.h>
#include <maya/MColor.h>
#include <maya/MUintArray.h>
#include <maya/MFloatPointArray.h>
#include <maya/MFloatVectorArray.h>
#include <maya/MColorArray.h>
#include <maya/MMatrix.h>
#include <maya/MIntArray.h>
#include <maya/M3dView.h>

#include <QtCore/QObject>


class QKeyEvent;

struct BrushConfig
{
	MPoint brushPos;
	MVector brushNormal;
	MColor brushColor;
	float brushSize;
	float brushWidth;
	bool isHit = false;
	double opacity = 1.0;
	double value = 1.0;

	MMatrix worldMat;
};

enum class BrushMode:uint8_t
{
	kNormal,
	kBrushSize
};

enum class PaintOperation:uint8_t
{
	kReplace,
	kAdd,
	kSmooth
};

class skinPainterContext:public QObject, public MPxContext
{
public:
	skinPainterContext();
	virtual ~skinPainterContext();

	virtual void toolOnSetup( MEvent & event ) override;
	virtual void toolOffCleanup() override;
	
	virtual MStatus doPress( MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context) override;
	virtual MStatus doRelease( MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context) override;
	virtual MStatus doPtrMoved( MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context) override;
	virtual MStatus doDrag( MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context) override;

	virtual bool eventFilter(QObject *watched, QEvent *event) override;

	void SetBrushColor(double r, double g, double b);
	void SetBrushOpacity(double opacity);
	void SetBrushValue(double val);
	void SetDrawMesh(const MDagPath& dagpathMesh);

	void SetVtxIndices(const MIntArray& inTriangle, const MIntArray& inTriangleStrip, const std::vector<MIntArray> inWireframe);
	void SetPaintJointIndex(unsigned int jointIdx);
	//void UpdateVtxColors();
	void UpdateInfluenceJnt(const MIntArray& influenceJnts);
	void SetInfluenceJointNum(unsigned int jntNum);
	void SetPaintOperation(const PaintOperation& op);
private:
	void UpdateBrushPos(MEvent & event, const MHWRender::MFrameContext& context);
	void DrawBrush(MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context);
	//void DrawMeshWireframe(MHWRender::MUIDrawManager& drawMgr);
	//void DrawMesh(MHWRender::MUIDrawManager& drawMgr);
	
	void doKeyPress(QKeyEvent* keyEvent);
	void doKeyRelease(QKeyEvent* keyEvent);

	void SetBrushSize(float size);
	float BrushSize() const;
	//void UpdateMeshPoints();

	void GetPointsInBrushRange(MIntArray& outVtxIndexInRange);
	void DrawWeightPoints(const MIntArray& inVtxIndices, MHWRender::MUIDrawManager& drawMgr);
	void DrawEffects(MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context);
	void AddWeight();
	void ReplaceWeight();
	void SmoothWeight();
	void GetNeighborPoints(int findPoint, MIntArray& outNeighborPoints);
	double GetVtxWeight(int vtxIndex, int jointIndex);
	void SetVtxWeight(int vtxIndex, int jointIndex, double weight);
	void RefreshDeformer();
	double Lerp(double start, double end, double ratio, double scale = 1.0);
	void PaintWeights();
	bool IsJntLocked(int jntIdx);
public:
	static MString toolTitle;
	static MString toolHelpText;
protected:
	MDagPath drawMesh;
	BrushConfig brush;
	BrushMode brushMode;
	PaintOperation paintOperation;

	MPoint currentCursorPos;
	MPoint lastCursorPos;
	bool bUpdateBrushPos;

	// vtx index
	MUintArray triangleIndoces;
	MUintArray triangleStripIndoces;
	std::vector<MUintArray> wireframeIndices;
	
	MFloatPointArray meshVertices;
	MFloatVectorArray meshVtxNormals;
	MColorArray vtxColors;

	M3dView view3D;
	
	unsigned int currentPaintJointIndex;
	unsigned int numInfluenceJoints;
	MIntArray currentUnlockJointIndices;
};
